#ifndef PANDA_APP_NATIVE_ENTRY_ANI_HELPERS_H
#define PANDA_APP_NATIVE_ENTRY_ANI_HELPERS_H

#include "ani.h"
#include <cstdio>
#include <string>

// static inline std::string addEndL(const char * str) {
// std::string strL = str;
// strL += '\n';

// return strL;
//}

// #define LOG(msg) fprintf(stdout, addEndL(msg).c_str());
// #define LOGI(msg, ...) fprintf(stdout, addEndL(msg).c_str(), ##__VA_ARGS__);
// #define LOGE(msg, ...) fprintf(stderr, addEndL(msg).c_str(), ##__VA_ARGS__);
// #define LOG_PUBLIC ""

// template<typename... Args>
// static void InteropFatalError(const char *msg, Args&&... Ts) {
// LOGE(msg, std::forward<Args>(Ts)...);
//}

#define INTEROP_FATAL(msg, ...)                                                                                        \
  do {                                                                                                                 \
    fprintf(stderr, msg "\n", ##__VA_ARGS__);                                                                          \
    abort();                                                                                                           \
  } while (0)

static ani_env *getEnv() {
  ani_vm *vms[] = {nullptr};
  ani_size vmCount = 0;
  ANI_GetCreatedVMs(vms, sizeof(vms) / sizeof(ani_vm *), &vmCount);

  if (vmCount == 0 || !vms[0])
    return nullptr;

  ani_env *res = nullptr;
  vms[0]->GetEnv(ANI_VERSION_1, &res);
  return res;
}

static void printStack() {
  auto *env = getEnv();
  if (!env)
    return;

  ani_boolean isError = false;
  env->ExistUnhandledError(&isError);
  if (isError) {
    env->DescribeError();
  }
}

#define CHECK_ANI_FATAL(result)                                                                                        \
  do {                                                                                                                 \
    ani_status ___res___ = (result);                                                                                   \
    if (___res___ != ANI_OK) {                                                                                         \
      printStack();                                                                                                    \
      INTEROP_FATAL("ANI function failed (status: %d) at " __FILE__ ": %d", ___res___, __LINE__);                      \
    }                                                                                                                  \
  } while (0)

static inline std::string getAniString(ani_env *env, ani_string aniStr) {
  ani_size strLen{};
  CHECK_ANI_FATAL(env->String_GetUTF8Size(aniStr, &strLen));
  ++strLen; // why? zero terminal???

  std::string str(strLen, '#');
  ani_size wasWrote{};
  CHECK_ANI_FATAL(env->String_GetUTF8(aniStr, str.data(), strLen, &wasWrote));

  if (wasWrote + 1 != strLen) {
    INTEROP_FATAL("getAniString wrote not full length. strLen: %zu wasWrote: %zu, str: %s", strLen, wasWrote,
                  str.data());
  }

  return str;
}

#endif // PANDA_APP_NATIVE_ENTRY_ANI_HELPERS_H
